package com.xmlit.project.client;

import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;
import com.xmlit.project.engine.struct.Struct;
import com.xmlit.project.engine.struct.StructChoice;
import com.xmlit.project.engine.struct.StructSequence;
import com.xmlit.project.engine.struct.StructSimple;
import com.xmlit.project.engine.struct.impl.StructChoiceImpl;
import com.xmlit.project.engine.struct.impl.StructSequenceImpl;
import com.xmlit.project.engine.struct.impl.StructSimpleImpl;

import static com.xmlit.project.client.Main.*;

public class TreeToStruct {

	public static void getTreeNode(Struct parent, TreeGrid treeGrid,
			TreeNode node) {
		node.setAttribute(Name, parent.getName());
		node.setAttribute(Min, parent.getMinOccurrences());
		node.setAttribute(Max, parent.getMaxOccurrences());
		node.setAttribute(Prefix, parent.getPrefix());
		node.setAttribute(Suffix, parent.getSuffix());

		if (parent instanceof StructSequence) {
			node.setAttribute(Type, Sequence);
			node.setAttribute(Delimiter,
					((StructSequence) parent).getDelimiter());
			node.setAttribute(Lookahead,
					((StructSequence) parent).getLookahead());
			node.setAttribute(Not, ((StructSequence) parent).isNegative());
		} else if (parent instanceof StructChoice) {
			node.setAttribute(Type, Choice);
		} else {
			node.setAttribute(Type, Simple);
			node.setAttribute(Regex, ((StructSimple) parent).getSimplePattern());
			node.setAttribute(AllowedChars,
					((StructSimple) parent).getAllowedChars());
			node.setAttribute(AllowedValues,
					((StructSimple) parent).getAllowedValues());
			node.setAttribute(minLength,
					"" + ((StructSimple) parent).getMinLength());
			node.setAttribute(maxLength,
					"" + ((StructSimple) parent).getMaxLength());

		}

		if (parent.getChildren() != null)
			for (Struct child : parent.getChildren()) {
				TreeNode newNode = new TreeNode();
				treeGrid.getTree().add(newNode, node);
				getTreeNode(child, treeGrid, newNode);
			}

	}

	public static Struct getStruct(TreeGrid treeGrid, TreeNode rootNode,
			Struct parent) {
		Struct current = null;
		if (Main.Sequence.equals(rootNode.getAttribute(Type))) {
			current = new StructSequenceImpl(rootNode.getAttribute(Name));
			((StructSequenceImpl) current).setDelimiter(handleEscape(rootNode
					.getAttribute(Delimiter)));
			((StructSequenceImpl) current).setLookahead(handleEscape(rootNode
					.getAttribute(Lookahead)));

			((StructSequenceImpl) current).setNegative(rootNode
					.getAttributeAsBoolean(Not));

		} else if (Main.Choice.equals(rootNode.getAttribute(Type))) {
			current = new StructChoiceImpl(rootNode.getAttribute(Name));
		} else {
			current = new StructSimpleImpl(rootNode.getAttribute(Name));
			((StructSimpleImpl) current).setSimplePattern(handleEscape(rootNode
					.getAttribute(Regex)));
			((StructSimpleImpl) current).setAllowedChars(handleEscape(rootNode
					.getAttribute(AllowedChars)));
			((StructSimpleImpl) current).setAllowedValues(handleEscape(rootNode
					.getAttribute(AllowedValues)));
			if (rootNode.getAttribute(minLength) != null)
				((StructSimpleImpl) current).setMinLength(Integer
						.parseInt(rootNode.getAttribute(minLength)));
			if (rootNode.getAttribute(maxLength) != null)
				((StructSimpleImpl) current).setMaxLength(Integer
						.parseInt(rootNode.getAttribute(maxLength)));
		}
		if (parent != null) {
			parent.addChild(current);
		}
		if (rootNode.getAttributeAsDouble(Min) != null)
			current.setMinOccurrences(rootNode.getAttributeAsDouble(Min)
					.intValue());
		if (rootNode.getAttributeAsDouble(Max) != null)
			current.setMaxOccurrences(rootNode.getAttributeAsDouble(Max)
					.intValue());

		current.setPrefix(handleEscape(rootNode.getAttribute(Prefix)));
		current.setSuffix(handleEscape(rootNode.getAttribute(Suffix)));

		for (TreeNode node : treeGrid.getTree().getChildren(rootNode)) {
			getStruct(treeGrid, node, current);
		}

		return current;
	}

	private static String handleEscape(String attribute) {
		if (attribute == null) {
			return null;
		}
		String result = attribute.replace("\\r", "\r");
		result = result.replace("\\n", "\n");

		return result;
	}

	private static String handleUnEscape(String attribute) {
		if (attribute == null) {
			return null;
		}
		String result = attribute.replace("\r", "\\r");
		result = result.replace("\n", "\\n");

		return result;
	}

}
